package org.yang.restgenerator.code;

import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import org.beetl.core.GroupTemplate;
import org.beetl.core.Template;
import org.beetl.core.resource.ClasspathResourceLoader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.yang.restgenerator.config.Conf;
import org.yang.restgenerator.entity.Column;
import org.yang.restgenerator.entity.Table;
import org.yang.restgenerator.service.GeneratorService;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author shichenyang
 */
@Service
public class Code {
    @Autowired
    private GeneratorService generatorService;

    @Autowired
    private Conf conf;

    public List<String> loadTemplate(){
        List<String> templates=new ArrayList<>();
//        templates.add("generator/add.html.btl");
        templates.add("generator/controller.java.btl");
        templates.add("generator/entity.java.btl");
//        templates.add("generator/index.html.btl");
        templates.add("generator/mapper.java.btl");
        templates.add("generator/mapper.xml.btl");
        templates.add("generator/service.java.btl");
        templates.add("generator/serviceimpl.java.btl");
//        templates.add("generator/update.html.btl");
        return templates;
    }

    public byte [] code(List<String> tableName, ZipOutputStream zip) throws IOException {
        ClasspathResourceLoader  resourceLoader = new ClasspathResourceLoader();
        org.beetl.core.Configuration cfg =  org.beetl.core.Configuration.defaultConfiguration();
        GroupTemplate gt = new GroupTemplate(resourceLoader, cfg);
        for (String t:tableName){

            Table table=generatorService.getOne(t);
            List<Column> columns=generatorService.getByColName(t);

            Map<String,Object> shard=new HashMap<>();
            shard.put("table",table);
            shard.put("columns",columns);
            shard.put("mainPath",conf.getMainPath());
            shard.put("email",conf.getEmail());
            shard.put("author",conf.getAuthor());
            shard.put("daoPackage",conf.getMainPath()+"."+conf.getModuleName()+".dao");
            shard.put("commonPackage",conf.getMainPath()+"."+conf.getModuleName()+".org.yang.order.food.common");
            shard.put("entityPackage",conf.getMainPath()+"."+conf.getModuleName()+".entity");
            shard.put("servicePackage",conf.getMainPath()+"."+conf.getModuleName()+".service");
            shard.put("serviceimplPackage",conf.getMainPath()+"."+conf.getModuleName()+".service.impl");
            shard.put("controllerPackage",conf.getMainPath()+"."+conf.getModuleName()+".controller");

            gt.setSharedVars(shard);
            List<String> templates=loadTemplate();
            for (String item:templates){
                StringWriter sw = new StringWriter();
                Template tt=gt.getTemplate(item);
                tt.renderTo(sw);
                zip.putNextEntry(new ZipEntry(getFileName(item.substring(item.indexOf("/")+1),table.getEntityName(),conf.getMainPath(),conf.getModuleName()) ));
                IOUtils.write(sw.toString(), zip, "UTF-8" );
                IOUtils.closeQuietly(sw);
                zip.closeEntry();
            }
        }
        return null;
    }
    public static Configuration getConfig() {
        try {
            return new PropertiesConfiguration("generator.properties" );
        } catch (ConfigurationException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String columnToJava(String columnName) {
        return WordUtils.capitalizeFully(columnName, new char[]{'_'}).replace("_", "" );
    }
    public static String tableToJava(String tableName, String tablePrefix) {
        if (StringUtils.isNotBlank(tablePrefix)) {
            tableName = tableName.replace(tablePrefix, "" );
        }
        return columnToJava(tableName);
    }


    public static String getFileName(String template, String className, String packageName, String moduleName) {
        String packagePath = "main" + File.separator + "java" + File.separator;
        if (StringUtils.isNotBlank(packageName)) {
            packagePath += packageName.replace(".", File.separator) + File.separator + moduleName + File.separator;
        }

        if (template.contains("entity.java.btl" )) {
            return packagePath + "entity" + File.separator + className + ".java";
        }

        if (template.contains("dao.java.btl" )) {
            return packagePath + "dao" + File.separator + className + "Dao.java";
        }

        if (template.contains("service.java.btl" )) {
            return packagePath + "service" + File.separator + className + "Service.java";
        }

        if (template.contains("serviceimpl.java.btl" )) {
            return packagePath + "service" + File.separator + "impl" + File.separator + className + "ServiceImpl.java";
        }

        if (template.contains("controller.java.btl" )) {
            return packagePath + "controller" + File.separator + className + "Controller.java";
        }

        if (template.contains("mapper.xml.btl" )) {
            return "main" + File.separator + "resources" + File.separator + "mapper" + File.separator + className + "Mapper.xml";
        }

        if (template.contains("mapper.java.btl")){
            return packagePath + "dao" + File.separator + className + "Mapper.java";
        }
        if (template.contains("index.html.btl" )) {
            return "main" + File.separator + "resources" + File.separator + "templates"  + File.separator+StringUtils.uncapitalize(className)+File.separator + StringUtils.uncapitalize(className) + ".html";
        }

        if (template.contains("add.html.btl" )) {
            return "main" + File.separator + "resources" + File.separator + "templates"  + File.separator+StringUtils.uncapitalize(className)+File.separator+ "add"+className + ".html";
        }
        if (template.contains("update.html.btl" )) {
            return "main" + File.separator + "resources" + File.separator + "templates"  + File.separator+StringUtils.uncapitalize(className)+File.separator+ "update"+className + ".html";
        }
        return null;
    }
}
